package com.zone.domain.strategy.service.armory;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import com.google.common.collect.Range;
import com.zone.domain.acticity.model.entity.ActivityEntity;
import com.zone.domain.acticity.repository.IActivityRepository;
import com.zone.domain.strategy.model.entity.StrategyAwardEntity;
import com.zone.domain.strategy.repository.IStrategyRepository;
import com.zone.domain.strategy.service.armory.assemble.StrategyAssembleBroadcaster;
import com.zone.types.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author: zongzi
 * @description: TODO
 * @date: 2024/5/26
 */
@Slf4j
@Service
public class StrategyArmoryDispatch implements IStrategyArmory, IStrategyDispatch {
    @Autowired
    private IStrategyRepository strategyRepository;
    @Autowired
    private StrategyAssembleBroadcaster strategyAssembleBroadcaster;
    @Autowired
    private IActivityRepository activityRepository;

    @Override
    public void assembleLotteryStrategyByActivity(Long activityId) {
        ActivityEntity activityEntity = activityRepository.queryActivity(activityId);
        this.assembleLotteryStrategy(activityEntity.getStrategyId());
    }

    @Override
    public void assembleLotteryStrategy(Long strategyId) {
        // 获取策略明细集合
        List<StrategyAwardEntity> strategyAwardEntities = strategyRepository.listStrategyAward(strategyId);
        Validate.notEmpty(strategyAwardEntities, "未查询到抽奖活动，请求确认！");

        // 将配置的规则模型广播到各个处理器
        strategyAssembleBroadcaster.broadcastAssemble(strategyId, strategyAwardEntities);
    }

    @Override
    public Integer getRandomAwardId(Long strategyId) {
        return this.getRandomAwardId(String.valueOf(strategyId));
    }

    @Override
    public Integer getRandomAwardId(Long strategyId, String ruleWeightValue) {
        return this.getRandomAwardId(String.format("%s_%s", strategyId, ruleWeightValue));
    }

    @Override
    public Integer getRandomAwardId(String key) {
        // 获取范围
        Integer tableRange = strategyRepository.getRateRange(key);
        // 获取奖品-概率表
        Map<Range<Integer>, Integer> awardRangeTable = strategyRepository.getAwardRangeTable(key);
        if (Objects.isNull(tableRange) || MapUtil.isEmpty(awardRangeTable)) {
            throw new BizException(String.format("策略还未装配: %s，请先进行策略装配!", key));
        }
        log.info("print award table start --------------");
        awardRangeTable.forEach((range, awardId) -> log.info("award range: {}, awardId: {}", range, awardId));
        log.info("print award table end   --------------");

        // 获取随机数
        int random = RandomUtil.getRandom().nextInt(1, tableRange);
        log.info("getRandomAwardId random = {}", random);

        // 计算随机数
        for (Range<Integer> rateRange : awardRangeTable.keySet()) {
            Integer awardId = awardRangeTable.get(rateRange);
            if (rateRange.contains(random)) {
                return awardId;
            }
        }
        return null;
    }
}
